home *** CD-ROM | disk | FTP | other *** search
Text File | 1999-06-25 | 13.3 KB | 626 lines | [TEXT/CWIE] |
- /*------------------------------------------------------------------------------
- #
- # Macintosh Developer Technical Support
- #
- # Simple Color QuickDraw Sample Application
- #
- # SillyBalls
- #
- # SillyBalls.c - C Source
- #
- # Copyright © 1988 Apple Computer, Inc.
- # All rights reserved.
- #
- # Versions: 1.0 8/88
- #
- # Components: SillyBalls.c August 1, 1988
- # SillyBalls.make August 1, 1988
- #
- # This is a very simple sample program that demonstrates how to use Color
- # QuickDraw. It is about two pages of code, and does nothing more than open
- # a color window and draw randomly colored ovals in the window.
- #
- # The purpose is to show how to get some initial results with Color QuickDraw.
- # It is a complete program and is very short to be as clear as possible.
- #
- # It does not have an Event Loop. It is not fully functional in the sense that
- # it does not do all the things you would expect a well behaved Macintosh
- # program to do, like size the window naturally, have an event loop, use menus,
- # etc.
- #
- # See Sample and TESample for the general structure and MultiFinder techniques that
- # we recommend that you use when building a new application.
- #
- ------------------------------------------------------------------------------*/
-
-
- // Version 1.0: 6/2/88
- // 7/20/88 DJB Converted to C
- //
- // purpose To demonstrate a simple color App using Color QuickDraw.
- // It draws colored balls in a color window, then uses colored
- // text inverted in the ball. The ball location and color is Random.
- //
- // This program was written by Bo3b Johnson, 1/88.
- //
- // The inverted Bob text was a Skippy Blair special concept,
- // kept for obvious aesthetic reasons.
-
- //MW -cut out some other program descriptions.-
-
- //MW ** Metrowerks note **
- // All changed code by Metrowerks is commented by "//MW".
- // There is one type of modification to the original source:
- // • Added argument type and return type to function definitions.
- // In order to pass with extended error checking on.
- //
- // 8/31/93 JA
-
-
- #include <Types.h>
- #include <Memory.h>
- #include <Quickdraw.h>
- #include <Fonts.h>
- #include <Events.h>
- #include <Menus.h>
- #include <Windows.h>
- #include <TextEdit.h>
- #include <Dialogs.h>
- #include <OSUtils.h>
- #include <ToolUtils.h>
- #include <SegLoad.h>
- #include <Sound.h>
- #include <QDOffscreen.h>
- #include <algorithm>
- #include <cmath>
- #include <list>
-
- #define assert(value) \
- do { if (!(value)) DebugStr("\pfailed"); } while (false)
-
- /* Constants */
-
- /* Globals */
-
- /* Prototypes */
-
- //
- // Main body of program SillyBalls
- //
-
- template <class T>
- inline T abs(T x)
- { return (x > 0) ? x : -x; }
-
- //
- // Initialize everything for the program, make sure we can run
- //
- extern "C" void AquireTarget(PicHandle inPic, Point* outPoints, UInt32* outCount);
-
- inline unsigned char AbsDelta(unsigned char a, unsigned char b)
- { return (a > b) ? (a - b) : (b - a); }
-
- class ZoomRect
- {
- public:
-
- ZoomRect()
- { }
- ZoomRect(const Rect& source, const Point& dest)
- {
- dstPoint = dest;
- drawRect = source;
-
- height = source.bottom - source.top;
- width = source.right - source.left;
-
- // Draw New
-
- PenMode(patXor);
- PenPat(&qd.gray);
- PenSize(4, 4);
-
- FrameRect(&drawRect);
-
- steps = width / 2;
- currentStep = 0;
-
- PenNormal();
- }
- bool NextRect()
- {
- PenMode(patXor);
- PenPat(&qd.gray);
- PenSize(4, 4);
-
- bool done = false;
-
- if (currentStep < steps)
- {
- ++currentStep;
-
- Rect newRect;
-
- // Draw new
-
- newRect.top = dstPoint.v * currentStep / steps;
- newRect.left = dstPoint.h * currentStep / steps;
- newRect.bottom = height - (height - dstPoint.v) * currentStep / steps;
- newRect.right = width - (width - dstPoint.h) * currentStep / steps;
-
- FrameRect(&newRect);
-
- // Erase old;
- FrameRect(&drawRect);
- drawRect = newRect;
- }
- else
- {
- // Erase Final
- FrameRect(&drawRect);
- done = true;
- }
- PenNormal();
- return done;
- }
-
- private:
- Rect drawRect;
- int steps;
- int currentStep;
- Point dstPoint;
- short height;
- short width;
- };
-
- static void ZoomRects(const Rect& source, const Point& dest)
- {
- ZoomRect zoomRect(source, dest);
- while (!zoomRect.NextRect())
- { }
- }
-
- class PlaySound
- {
- public:
- PlaySound(const unsigned char* file);
- ~PlaySound();
- private:
- SndChannelPtr chan;
- short refNum;
- };
-
- PlaySound::PlaySound(const unsigned char* file) :
- chan (NULL)
- {
- OSErr error;
-
- error = FSOpen(file, 0, &refNum);
- assert (error == noErr);
-
- error = SndNewChannel(&chan, sampledSynth, initStereo, nil);
- assert (error == noErr);
-
- error = SndStartFilePlay(chan, refNum, 0, 0, nil, nil, nil, true);
- assert (error == noErr);
- }
-
- PlaySound::~PlaySound()
- {
- OSErr error;
-
- error = SndStopFilePlay(chan, true);
- assert (error == noErr);
-
- error = SndDisposeChannel(chan, true);
- assert (error == noErr);
-
- FSClose(refNum);
- }
-
- struct Hit
- {
- int hitValue;
- Point hitLoc;
- bool isMarked;
-
- Hit() :
- hitValue(0x7FFFFFFF),
- isMarked(false)
- { }
-
- operator < (const Hit& x) const
- { return hitValue > x.hitValue; }
- };
-
- typedef std::list<ZoomRect> ZoomList;
-
- void AquireTarget(PicHandle inPic, Point* outPoints, UInt32* outCount)
- {
- GWorldPtr oldWorld;
- GDHandle oldDevice;
- GetGWorld(&oldWorld, &oldDevice);
-
- Hit hitArray[5];
- int screenHeight;
- int screenWidth;
-
- CGrafPort port;
- GWorldPtr world;
-
- ZoomList zoomList;
-
- {
- PlaySound busyChild("\pBusy Child.aif");
-
- // start doing work.
-
- const int imageSize = 32;
-
- if (inPic == nil)
- {
- SysBeep(10);
- return;
- }
-
- *outCount = 0;
-
- OSErr error = NewGWorld(&world, 8, &qd.screenBits.bounds, GetCTable(k8IndexedGrayPixelFormat), NULL, useTempMem);
- assert (error == noErr);
-
- PixMap** map = GetGWorldPixMap(world);
- LockPixels(map);
-
- // Extract the useful attributes
-
- unsigned char* baseAddr = (unsigned char*)map[0]->baseAddr;
- int rowBytes = map[0]->rowBytes & 0x3FFF;
-
- screenWidth = qd.screenBits.bounds.right - qd.screenBits.bounds.left;
- screenHeight = qd.screenBits.bounds.bottom - qd.screenBits.bounds.top;
- int screenBytes = rowBytes * screenHeight;
-
- // Plot the icon and extract
-
- SetGWorld(world, NULL);
-
- Rect rect = { 0, 0, 32, 32 };
- EraseRect(&rect);
- DrawPicture(inPic, &rect);
-
- unsigned char image[imageSize][imageSize + 1];
- unsigned char edgeWeight[imageSize][imageSize];
-
- for (int i = 0; i < imageSize; ++i)
- {
- BlockMove(baseAddr + (rowBytes * i), &image[i], imageSize);
- image[i][imageSize] = image[i][imageSize - 1]; // Replicate edge pixel for edge finder
- }
-
- for (int v = 0; v < imageSize; ++v)
- {
- for (int h = 0; h < imageSize; ++h)
- {
- edgeWeight[v][h] = AbsDelta(image[v][h],image[v][h + 1]);
- }
- }
-
- // Copy the screen to the offscreen
-
-
- CopyBits(&qd.screenBits, (BitMap*)*map, &qd.screenBits.bounds,
- &qd.screenBits.bounds, srcCopy, NULL);
-
- SetGWorld(oldWorld, oldDevice);
-
- unsigned char* srcPtr = baseAddr;
-
- const int worstPossible = 0x7FFFFFFF;
- int worstHit = worstPossible;
-
- // Set the port for drawing
-
- OpenCPort(&port);
-
- int bufferSize = rowBytes / 10;
-
- Rect rectBuffer[250] = {0};
- bool endOnce = false;
- int bufferPos = 0;
- int tailPos = 0;
-
- TextMode(srcXor);
- TextSize(32);
- TextFont(GetSysFont());
-
- // Draw new
- short width = StringWidth("\pScanning For Possible Targets...");
- MoveTo((screenWidth - width) / 2, 100);
- DrawString("\pScanning For Possible Targets...");
-
- for (int count = 0; count < screenBytes; ++count)
- {
- unsigned long acumulate = 0;
-
- for (int sampleV = 0; sampleV < imageSize; ++sampleV)
- {
- for (int sampleH = 0; sampleH < imageSize; ++sampleH)
- {
- unsigned char imageDif = AbsDelta(*(srcPtr + (sampleV - (imageSize / 2)) * rowBytes + (sampleH - (imageSize / 2))), image[sampleV][sampleH]);
- acumulate += edgeWeight[sampleV][sampleH] * imageDif;
- }
- }
-
- if ((count & 0x0000008F) == 0)
- {
- for (ZoomList::iterator iter(zoomList.begin());
- iter != zoomList.end();
- ++iter)
- {
- if ((*iter).NextRect()) iter = zoomList.erase(iter);
- }
- }
-
-
- if ((count & 0x000000FF) == 0)
- {
-
- if ((count & 0x00000FFF) == 0)
- {
- short width = StringWidth("\pScanning For Possible Targets...");
- MoveTo((screenWidth - width) / 2, 100);
- DrawString("\pScanning For Possible Targets...");
- }
-
- short vertical = (srcPtr - baseAddr) / rowBytes;
- short horizontal = (srcPtr - baseAddr) % rowBytes;
-
- rectBuffer[bufferPos].top = vertical - 10;
- rectBuffer[bufferPos].left = horizontal - 10;
- rectBuffer[bufferPos].bottom = rectBuffer[bufferPos].top + 20;
- rectBuffer[bufferPos].right = rectBuffer[bufferPos].left + 20;
-
- InvertOval(&rectBuffer[bufferPos]);
-
- if (endOnce || (bufferPos == (bufferSize - 1)))
- {
- InvertOval(&rectBuffer[tailPos]);
- if (++tailPos == bufferSize) tailPos = 0;
- endOnce = true;
- }
- if (++bufferPos == bufferSize) bufferPos = 0;
- }
-
- if (acumulate < worstHit)
- {
- short vertical = (srcPtr - baseAddr) / rowBytes;
- short horizontal = (srcPtr - baseAddr) % rowBytes;
-
- bool foundMatch = false;
- int foundIndex = 0;
-
- // Check and see if we already have a local hit...
- for (int i = 0; i < 5; ++i)
- {
- if ((abs(hitArray[i].hitLoc.v - vertical) < 16) &&
- (abs(hitArray[i].hitLoc.h - horizontal) < 16))
- {
- foundMatch = true;
- foundIndex = i;
-
- if (acumulate < hitArray[i].hitValue)
- {
- hitArray[i].hitValue = acumulate;
- hitArray[i].hitLoc.v = vertical;
- hitArray[i].hitLoc.h = horizontal;
- }
- break;
- }
- }
- if (!foundMatch)
- {
- for (int i = 0; i < 5; ++i)
- {
- if (hitArray[i].hitValue == worstHit)
- {
- foundMatch = true;
- foundIndex = i;
-
- hitArray[i].hitValue = acumulate;
- hitArray[i].hitLoc.v = vertical;
- hitArray[i].hitLoc.h = horizontal;
- hitArray[i].isMarked = false;
- break;
- }
- }
- }
-
- if (foundMatch
- && (worstHit != worstPossible)
- && ((acumulate * 100 / worstHit) < 99)
- && !hitArray[foundIndex].isMarked)
- {
- hitArray[foundIndex].isMarked = true;
- Rect tempRect = {0, 0, screenWidth, screenHeight};
- Point point = { vertical, horizontal };
-
- zoomList.push_back(ZoomRect(tempRect, point));
-
- #if 0
- ZoomRects(tempRect, point);
- #endif
- }
-
- worstHit = 0;
- for (int i = 0; i < 5; ++i)
- {
- if (hitArray[i].hitValue > worstHit)
- worstHit = hitArray[i].hitValue;
- }
- }
-
- srcPtr += 1;
- }
-
- // Clean up the scan
-
- for (int i = 0; i < (bufferSize - 1); ++i)
- {
- InvertOval(&rectBuffer[tailPos]);
- if (++tailPos == bufferSize) tailPos = 0;
- }
-
- // Finish the sound
- }
- {
- PlaySound gunShots("\pGun Shots.aif");
-
- short width = StringWidth("\pTarget Acquired...");
- MoveTo((screenWidth - width) / 2, 100);
- DrawString("\pTarget Acquired...");
-
- std::sort(&hitArray[0], &hitArray[5]);
-
- short crossX = 0;
- short crossY = 0;
-
- for (int i = 0; i < 5; ++i)
- {
- PenMode (srcXor);
- PenSize (2, 2);
-
- short horizontal = hitArray[i].hitLoc.h;
- short vertical = hitArray[i].hitLoc.v;
-
- if (i == 0)
- {
- // draw new
-
- MoveTo(crossX, 0);
- LineTo(crossX, screenHeight);
- MoveTo(0, crossY);
- LineTo(screenWidth, crossY);
- }
-
- int count = 0;
-
- while ((crossX != horizontal) || (crossY != vertical))
- {
- for (ZoomList::iterator iter(zoomList.begin());
- iter != zoomList.end();
- ++iter)
- {
- if ((*iter).NextRect()) zoomList.pop_back();
- }
-
- if ((++count & 0x00000007) == 0)
- {
- unsigned long temp;
- Delay (1, &temp);
- }
-
- if (crossX != horizontal)
- {
- // draw new
- short newCrossX = crossX + ((horizontal < crossX) ? -1 : 1);
-
- MoveTo(newCrossX, 0);
- LineTo(newCrossX, screenHeight);
-
- // erase old
- MoveTo(crossX, 0);
- LineTo(crossX, screenHeight);
-
- crossX = newCrossX;
- }
-
- if (crossY != vertical)
- {
- // draw new
- short newCrossY = crossY + ((vertical < crossY) ? -1 : 1);
-
- MoveTo(0, newCrossY);
- LineTo(screenWidth, newCrossY);
-
- // erase old
- MoveTo(0, crossY);
- LineTo(screenWidth, crossY);
-
- crossY = newCrossY;
- }
- }
-
- if ( (hitArray[i].hitValue < 3000000) || (i == 4))
- {
- // erase old
-
- MoveTo(crossX, 0);
- LineTo(crossX, screenHeight);
- MoveTo(0, crossY);
- LineTo(screenWidth, crossY);
-
- Rect tempRect = {0, 0, screenWidth, screenHeight};
- Point point = { hitArray[i].hitLoc.v, hitArray[i].hitLoc.h };
-
- ZoomRects(tempRect, point);
-
- Rect rect;
- rect.top = hitArray[i].hitLoc.v - 10;
- rect.left = hitArray[i].hitLoc.h - 10;
- rect.bottom = rect.top + 20;
- rect.right = rect.left + 20;
-
- PenMode(subPin);
- RGBColor color = { 0, 0xFFFF, 0xFFFF };
- RGBForeColor(&color);
- PaintOval(&rect);
- {
- // Reset the forecolor
- RGBColor color = { 0, 0, 0 };
- RGBForeColor(&color);
- }
- PenNormal();
-
- if (i != 4)
- {
- // Draw Again
-
- PenMode (srcXor);
- PenSize (2, 2);
-
- MoveTo(crossX, 0);
- LineTo(crossX, screenHeight);
- MoveTo(0, crossY);
- LineTo(screenWidth, crossY);
- }
-
- *outPoints++ = hitArray[i].hitLoc;
- (*outCount)++;
- }
-
- }
-
- {
- short width = StringWidth("\pTarget Acquired...");
- MoveTo((screenWidth - width) / 2, 100);
- DrawString("\pTarget Acquired...");
- }
-
- unsigned long temp;
- Delay(60, &temp);
- PenNormal();
-
- // Finish the sound
- }
-
- // Clean-up the GWorld
-
- CloseCPort(&port);
- DisposeGWorld(world);
-
- SetGWorld(oldWorld, oldDevice);
-
- }
-
-
-